package ChatSystem;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import chatsystemTDa2.FileResponse;

/**
 * A class that encapsulates a TCP socket serving the purpose of receiving files.
 * When the thread is launched, it waits for other instances of the TCPReceiver to complete the transfer, and then starts to download the file.
 *
 */
public class TCPReceiver extends Thread {
	private final ChatMessage.ChatFileMessage _message;
	private ServerSocket _socket;
	private final UDPSender _udp;
	private static final Object _receiverLock = new Object();
	
	/**
	 * Initializes the receiver.
	 * @param udp The UDPSender that will be used to notify the remote user of the approval
	 * @param message The message containing the file to send
	 */
	public TCPReceiver(UDPSender udp, ChatMessage.ChatFileMessage message) {
		_message = message;
		_udp = udp;
	}
	
	@Override
	public void run() {
		// Prevents multiples files to be received at the same time: impossible because we would use the same TCP port for both sockets. So we just wait for the transfer to complete or to fail.
		synchronized(_receiverLock) {
			try {
				_udp.sendMessage(new FileResponse(true, _message.getFilename()), _message.getSender().getAddress(), _message.getSender().getPort());
				
				_socket = new ServerSocket(_message.getRecipient().getPort());

				Socket client = _socket.accept();
				_message.setState(ChatMessage.ChatFileMessage.State.Transfer);
				FileOutputStream fileStream = new FileOutputStream(_message.getPath());
				InputStream out = client.getInputStream();
				
				int count;
				// Transfer the file using at most 1 megabyte chunks
				byte[] buffer = new byte[1 << 20];
				while((count = out.read(buffer)) > 0) {
				  fileStream.write(buffer, 0, count);
				}
				
				fileStream.close();
				_socket.close();
				
				_message.setState(ChatMessage.ChatFileMessage.State.Completed);
			}
			catch(Exception e) {
				_message.setState(ChatMessage.ChatFileMessage.State.Error);
			}
		}
	}
}
